package com.srmt.feishu.client.impl.services;

import com.lark.oapi.Client;
import com.lark.oapi.service.sheets.v3.model.*;
import com.srmt.document.feishu.internal.table.util.SheetCoordinateHelper;
import com.srmt.feishu.client.SheetsService;
import com.srmt.feishu.client.impl.SheetsV2ApiClient;
import com.srmt.feishu.client.model.ProtectedDimension;
import com.srmt.feishu.client.util.ResponseValidator;

import java.util.List;
import java.util.Map;

/**
 * 默认的电子表格服务实现
 *
 * 集成了Sheets v2和v3 API支持，并使用ResponseValidator统一处理v3 API响应
 *
 * @author SRMT Development Team
 * @since 2.0.0
 * @version 6.0.0 添加统一响应处理
 */
class DefaultSheetsServiceImpl implements SheetsService {
    private final Client client;
    private final SheetsV2ApiClient v2Client;

    DefaultSheetsServiceImpl(Client client) {
        this.client = client;
        this.v2Client = new SheetsV2ApiClient(client);
    }

    @Override
    public Sheet getSheet(String spreadsheetToken, String sheetId) throws Exception {
        GetSpreadsheetSheetReq req = GetSpreadsheetSheetReq.newBuilder()
                .spreadsheetToken(spreadsheetToken)
                .sheetId(sheetId)
                .build();
        GetSpreadsheetSheetResp resp = client.sheets().v3().spreadsheetSheet().get(req);
        return ResponseValidator.validateAndExtract(
                resp,
                "getSheet",
                r -> r.getData().getSheet()
        );
    }

    @Override
    public com.lark.oapi.service.sheets.v3.model.GetSpreadsheet getSpreadsheet(String spreadsheetToken) throws Exception {
        GetSpreadsheetReq req = GetSpreadsheetReq.newBuilder()
                .spreadsheetToken(spreadsheetToken)
                .build();
        GetSpreadsheetResp resp = client.sheets().v3().spreadsheet().get(req);
        return ResponseValidator.validateAndExtract(
                resp,
                "getSpreadsheet",
                r -> r.getData().getSpreadsheet()
        );
    }

    @Override
    public Sheet[] querySheets(String spreadsheetToken) throws Exception {
        QuerySpreadsheetSheetReq req = QuerySpreadsheetSheetReq.newBuilder()
                .spreadsheetToken(spreadsheetToken)
                .build();
        QuerySpreadsheetSheetResp resp = client.sheets().v3().spreadsheetSheet().query(req);
        return ResponseValidator.validateAndExtract(
                resp,
                "querySheets",
                r -> r.getData().getSheets()
        );
    }

    @Override
    public com.lark.oapi.service.sheets.v3.model.Spreadsheet createSpreadsheet(CreateSpreadsheetReq req) throws Exception {
        CreateSpreadsheetResp resp = client.sheets().v3().spreadsheet().create(req);
        return ResponseValidator.validateAndExtract(
                resp,
                "createSpreadsheet",
                r -> r.getData().getSpreadsheet()
        );
    }

    @Override
    public List<List<String>> getValues(String spreadsheetToken, String range) throws Exception {
        return v2Client.getValues(spreadsheetToken, range);
    }

    @Override
    public boolean updateValues(String spreadsheetToken, String range, List<List<String>> values) throws Exception {
        return v2Client.updateValues(spreadsheetToken, range, values);
    }

    @Override
    public boolean batchUpdateValues(String spreadsheetToken, Map<String, List<List<String>>> updates) throws Exception {
        return v2Client.batchUpdateValues(spreadsheetToken, updates);
    }

    @Override
    public boolean prependValues(String spreadsheetToken, String range, List<List<String>> values) throws Exception {
        return v2Client.prependValues(spreadsheetToken, range, values);
    }

    @Override
    public boolean appendValues(String spreadsheetToken, String range, List<List<String>> values) throws Exception {
        // Extract sheetId from range (format: "SheetId!A1:B2")
        String sheetId = range.contains("!") ? range.substring(0, range.indexOf("!")) : "Sheet1";
        return v2Client.appendValues(spreadsheetToken, sheetId, values);
    }

    @Override
    public boolean addDimensionRange(String spreadsheetToken, String sheetId, String dimension, int length) throws Exception {
        return v2Client.addDimensionRange(spreadsheetToken, sheetId, dimension, length);
    }

    @Override
    public boolean insertDimensionRange(String spreadsheetToken, String sheetId, String dimension,
                                      int startIndex, int endIndex) throws Exception {
        return v2Client.insertDimensionRange(spreadsheetToken, sheetId, dimension, startIndex, endIndex);
    }

    @Override
    public boolean deleteDimensionRange(String spreadsheetToken, String sheetId, String dimension,
                                       int startIndex, int endIndex) throws Exception {
        return v2Client.deleteDimensionRange(spreadsheetToken, sheetId, dimension, startIndex, endIndex);
    }

    @Override
    public boolean updateDimensionRange(String spreadsheetToken, String sheetId, String dimension,
                                       int startIndex, int endIndex, int size) throws Exception {
        return v2Client.updateDimensionRange(spreadsheetToken, sheetId, dimension, startIndex, endIndex, size);
    }

    @Override
    public boolean mergeCells(String spreadsheetToken, String sheetId,
                             int startRow, int startCol, int endRow, int endCol) throws Exception {
        // Convert to A1 notation using CoordinateConverter
        String range = String.format("%s!%s:%s", sheetId,
                SheetCoordinateHelper.convertToCellAddress(startRow, startCol),
                SheetCoordinateHelper.convertToCellAddress(endRow, endCol));
        return v2Client.mergeCells(spreadsheetToken, range, "MERGE_ALL");
    }

    @Override
    public boolean unmergeCells(String spreadsheetToken, String sheetId,
                               int startRow, int startCol, int endRow, int endCol) throws Exception {
        // Convert to A1 notation using CoordinateConverter
        String range = String.format("%s!%s:%s", sheetId,
                SheetCoordinateHelper.convertToCellAddress(startRow, startCol),
                SheetCoordinateHelper.convertToCellAddress(endRow, endCol));
        return v2Client.unmergeCells(spreadsheetToken, range);
    }

    @Override
    public boolean setCellStyle(String spreadsheetToken, String range, Object style) throws Exception {
        return v2Client.setCellStyle(spreadsheetToken, range, style);
    }

    @Override
    public boolean setDataValidation(String spreadsheetToken, String range, Object validation) throws Exception {
        return v2Client.setDataValidation(spreadsheetToken, range, validation);
    }

    @Override
    public boolean addProtectedDimension(String spreadsheetToken,
                                        List<ProtectedDimension> protectedDimensions,
                                        String userIdType) throws Exception {
        return v2Client.addProtectedDimension(spreadsheetToken, protectedDimensions, userIdType);
    }
}
